package handler

import (
	"google.golang.org/protobuf/reflect/protoreflect"
	"sync"
	"time"
)

type SyncCmdContextMap[K comparable, V CmdContext] struct {
	data sync.Map
}

func (m *SyncCmdContextMap[K, V]) Store(key K, value V) {
	m.data.Store(key, value)
}

func (m *SyncCmdContextMap[K, V]) Load(key K) (CmdContext, bool) {
	val, ok := m.data.Load(key)
	if !ok {
		return nil, false
	}
	return val.(V), true
}

func (m *SyncCmdContextMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
	// 调用原生 LoadOrStore（返回 interface{} 类型）
	rawActual, loaded := m.data.LoadOrStore(key, value)
	if loaded {
		// 若 key 已存在，将返回值断言为 V 类型
		actual = rawActual.(V)
	} else {
		// 若 key 不存在，返回新存储的 value（无需断言）
		actual = value
	}
	return actual, loaded
}

type CmdContextGroup struct {
	innerMap *SyncCmdContextMap[string, CmdContext]
}

var cmdContextGroup = &CmdContextGroup{
	innerMap: &SyncCmdContextMap[string, CmdContext]{},
}

func GetCmdContextGroup() *CmdContextGroup {
	return cmdContextGroup
}

func (group *CmdContextGroup) Register(ctxId string, ctx CmdContext) {
	if len(ctxId) == 0 || ctx == nil {
		return
	}

	group.innerMap.Store(ctxId, ctx)
}

func (group *CmdContextGroup) UnRegister(ctxId string) {
	if len(ctxId) == 0 {
		return
	}

	group.innerMap.data.Delete(ctxId)
}

func (group *CmdContextGroup) Broadcast(msgObj protoreflect.ProtoMessage) {
	if msgObj == nil {
		return
	}

	group.innerMap.data.Range(func(key, value interface{}) bool {
		if key == nil || value == nil {
			return true
		}

		value.(CmdContext).Write(msgObj)
		return true
	})
}

// GetActiveConnectionCount 获取当前活跃连接数
func (group *CmdContextGroup) GetActiveConnectionCount() uint32 {
	if group == nil || group.innerMap == nil {
		return 0
	}

	var activeConnections uint32 = 0
	currentTime := time.Now().UnixMilli()

	group.innerMap.data.Range(func(key, value interface{}) bool {
		if key != nil && value != nil {
			// 检查连接是否仍然活跃
			ctx, ok := value.(*CmdContextInnerWebsocket)
			if ok {
				// 如果连接在过去2分钟内有活动，则认为是活跃连接
				if currentTime-ctx.LastActiveTime < 120000 {
					activeConnections++
				}
			}
		}
		return true
	})

	return activeConnections
}
